﻿using System;
using Melee.Controller.Request;
using Melee.Controller.Routing;
using Melee.Controller.Storage;
using Melee.DataContract.Messaging;

namespace Melee.Controller.Handlers
{
    public abstract class RequestHandler
    {
        private RequestHandler m_NextHandler = null;
        protected RequestHandler NextHandler { get { return m_NextHandler; } }

        private Route m_Route = null;
        protected Route Route { get { return m_Route; } }

        public RequestHandler() { }

        public RequestHandler(string route)
        {
            m_Route = new Route(route);
        }

        public RequestHandler SetNextHandler(RequestHandler requestHandler)
        {
            m_NextHandler = requestHandler;
            return m_NextHandler;
        }

        public abstract void Handle(WebRequest webRequest);

        protected void Handle<T>(
            WebRequest webRequest,
            Func<WebRequest, T> getResponseCallback,
            Func<T, object> getResponseDataCallback) where T : ResponseBase
        {
            if (Route.Matches(webRequest))
            {
                T response = getResponseCallback(webRequest);
                webRequest.Storage.Add(HttpStorageKeys.Success, response.Success);
                if (response.Success)
                {
                    webRequest.Storage.Add(HttpStorageKeys.Data, getResponseDataCallback(response));
                }
                else
                {
                    webRequest.Storage.Add(HttpStorageKeys.Exception, response.Exception);
                    webRequest.Storage.Add(HttpStorageKeys.Message, response.Message);
                }
                webRequest.AsyncResult.SetCompleted();
            }
            else
            {
                NextHandler.Handle(webRequest);
            }
        }

        protected void SetAsComplete<T>(T response, Func<T, object> getResponseDataCallback, WebRequest webRequest) where T : ResponseBase
        {
            webRequest.Storage.Add(HttpStorageKeys.Success, response.Success);
            if (response.Success)
            {
                webRequest.Storage.Add(HttpStorageKeys.Data, getResponseDataCallback(response));
            }
            else
            {
                webRequest.Storage.Add(HttpStorageKeys.Exception, response.Exception);
                webRequest.Storage.Add(HttpStorageKeys.Message, response.Message);
            }
            webRequest.AsyncResult.SetCompleted();
        }
    }
}
